"""
---------------------------------------------------------------------
- File: exceptions.py
- Date: 2025/11/12
- Author: yangzhide
- Email: xxzjyzd@126.com
- Description: 全局异常处理，统一响应格式
---------------------------------------------------------------------
"""

from fastapi import FastAPI, Request, status
from fastapi.exceptions import RequestValidationError, HTTPException
from fastapi.responses import JSONResponse
from sqlalchemy.exc import IntegrityError

from app.core.response import ResponseError


def register_exception_handlers(app: FastAPI) -> None:
    """
    注册全局异常处理器
    """

    # HTTPException 处理器
    @app.exception_handler(HTTPException)
    async def http_exception_handler(request: Request, exc: HTTPException):
        """
        全局 HTTP 异常处理器， 用户抛出的HTTPException 异常
        """

        return JSONResponse(
            status_code=exc.status_code,
            content=ResponseError(code=exc.status_code, message=exc.detail, data=None).model_dump(),
        )

    # 请求体验证异常处理器
    @app.exception_handler(RequestValidationError)
    async def validation_exception_handler(request: Request, exc: RequestValidationError):
        """
        请求体验证异常处理器，请求体响应体验证失败
        """
        return JSONResponse(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            content=ResponseError(
                code=status.HTTP_422_UNPROCESSABLE_ENTITY, message=exc.errors(), data=None
            ).model_dump(),
        )

    # 数据库异常处理器
    @app.exception_handler(IntegrityError)
    async def integrity_error_handler(request: Request, exc: IntegrityError):
        """
        数据库异常处理器（如违反唯一约束）,
        在一对多、多对多关系
        单表会在api层进行处理
        """
        return JSONResponse(
            status_code=status.HTTP_409_CONFLICT,
            content=ResponseError(
                code=status.HTTP_409_CONFLICT, message="数据已存在,不能重复添加", data=None
            ).model_dump(),
        )

    # 其他异常处理器
    @app.exception_handler(Exception)
    async def exception_handler(request: Request, exc: Exception):
        """
        处理所有未被不会的异常处理器
        """
        return JSONResponse(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            content=ResponseError(
                code=status.HTTP_500_INTERNAL_SERVER_ERROR, message="服务器内部错误，请联系管理员", data=None
            ).model_dump(),
        )
